package com.fary.cloud.netflix.eureka.server;

import com.fary.beans.factory.annotation.Autowired;
import com.fary.cloud.netflix.eureka.server.event.EurekaRegistryAvailableEvent;
import com.fary.cloud.netflix.eureka.server.event.EurekaServerStartedEvent;
import com.fary.context.ApplicationContext;
import com.fary.context.ApplicationEvent;
import com.fary.context.SmartLifecycle;
import com.fary.context.annotation.Configuration;
import com.fary.core.Ordered;
import com.fary.web.context.ServletContextAware;
import com.netflix.eureka.EurekaServerConfig;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.servlet.ServletContext;

/**
 * 该类用于eureka服务的一些参数
 */
@Configuration(proxyBeanMethods = false)
public class EurekaServerInitializerConfiguration implements ServletContextAware, SmartLifecycle, Ordered {

    private static final Log log = LogFactory.getLog(EurekaServerInitializerConfiguration.class);

    // 包含服务注册中心有关的所有配置
    @Autowired
    private EurekaServerConfig eurekaServerConfig;

    private ServletContext servletContext;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private EurekaServerBootstrap eurekaServerBootstrap;

    // 当前eureka服务器状态
    private boolean running;

    // 定义order等级
    private int order = 1;

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    @Override
    public void start() {
        // 启动一个线程用于执行后续初始化动作减少主线程的压力
        new Thread(() -> {
            try {
                // TODO: is this class even needed now?
                eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
                log.info("Started Eureka Server");
                // 目前eureka服务种存在5种事件 该事件可以通过实现ApplicationListener接口来接受
                // EurekaRegistryAvailableEvent  eureka自身注册时触发内部通知事件
                // EurekaServerStartedEvent      eureka服务启动时触发内部通知事件
                // EurekaInstanceCanceledEvent   eureka客户端节点下线时触发内部通知事件
                // EurekaInstanceRenewedEvent    eureka客户端节点更新时触发内部通知事件
                // EurekaInstanceRegisteredEvent eureka客户端节点注册时触发内部通知事件
                publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
                // 修改eureka服务器状态
                EurekaServerInitializerConfiguration.this.running = true;
                publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
            } catch (Exception ex) {
                // Help!
                log.error("Could not initialize Eureka servlet context", ex);
            }
        }).start();
    }

    private EurekaServerConfig getEurekaServerConfig() {
        return this.eurekaServerConfig;
    }

    private void publish(ApplicationEvent event) {
        this.applicationContext.publishEvent(event);
    }

    @Override
    public void stop() {
        this.running = false;
        eurekaServerBootstrap.contextDestroyed(this.servletContext);
    }

    @Override
    public boolean isRunning() {
        return this.running;
    }

    @Override
    public int getPhase() {
        return 0;
    }

    @Override
    public boolean isAutoStartup() {
        return true;
    }

    @Override
    public void stop(Runnable callback) {
        callback.run();
    }

    @Override
    public int getOrder() {
        return this.order;
    }

}